#include "texture_pack.h"

#include <QDebug>
#include <QPixmap>
#include <QVariant>
#include <QVariantMap>

#include <QJson/Parser>

#include <quazip/quazip.h>
#include <quazip/quazipfile.h>

#include "pack_metadata.h"

struct TileSheetInfo {
  const char* path;
  int rows;
  int columns;
};

bool compareSheetNames(const TileSheet* a, const TileSheet* b) {
  return a->name() < b->name();
}

TexturePack::TexturePack(const TexturePack& other)
    : name_(other.name_), tile_sheets_(other.tile_sheets_) {}

TexturePack::TexturePack(const QString& name,
                         const QFileInfo& archive,
                         const TexturePack* minecraft_jar,
                         const PackMetadata* metadata,
                         QObject* parent)
    : QObject(parent), name_(name), minecraft_jar_(minecraft_jar), pack_metadata_(metadata) {
  QStringList tilesheet_paths = pack_metadata_->tilesheetPaths();
  QuaZip zip(archive.absoluteFilePath());
  zip.open(QuaZip::mdUnzip);
  QuaZipFile file(&zip);
  for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) {
    for (int i = 0; i < tilesheet_paths.size(); ++i) {
      if (file.getActualFileName() == tilesheet_paths.at(i)) {
        file.open(QIODevice::ReadOnly);
        QPixmap pmap;
        pmap.loadFromData(file.readAll());
        QSize size = metadata->tilesheetSize(tilesheet_paths.at(i));
        tile_sheets_.push_back(new TileSheet(
            file.getActualFileName(), pmap, size.height(), size.width(), metadata, this));
        file.close();
      } else if (file.getActualFileName() == "pack.txt") {
        // Read pack.txt to get a better name for the pack than the zipfile name.
        file.open(QIODevice::ReadOnly);
        QByteArray bytes = file.readLine();
        name_ = QString::fromUtf8(bytes.constData()).trimmed();
        // Many pack names begin with "The", which flows better in the UI if we make it lowercase.
        if (name_.startsWith("The ", Qt::CaseSensitive)) {
          name_ = QString("the %1").arg(name_.mid(4));
        }
        file.close();
      }
    }
  }
  zip.close();
  qSort(tile_sheets_.begin(), tile_sheets_.end(), compareSheetNames);
}

QString TexturePack::name() const {
  return name_;
}

TileSheet* TexturePack::tileSheetNamed(const QString& name) const {
  foreach (TileSheet* sheet, tile_sheets_) {
    if (sheet->name() == name) {
      return sheet;
    }
  }
  if (minecraft_jar_) {
    return minecraft_jar_->tileSheetNamed(name);
  } else {
    QDebug(QtFatalMsg) << "Unable to find tilesheet" << name << "in this or default texture pack!";
    return NULL;
  }
}
